home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------
-
- AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
- Mail Service Access Module
-
- written by Steve Falkenburg-- MacDTS
- ©1991-1993 Apple Computer, Inc.
-
- --------------
- change history
- --------------
-
- SJF 02/19/93 update for beta build b1
- SJF 10/29/92 update to a11 a11
- SJF 06/08/92 update to a8 a8
- SJF 02/15/92 first working version a4.5
- SJF 10/16/91 initial coding a3
-
- ---------------------------------------------------------------------*/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #include <string.h>
-
- #ifdef applec
- #include <strings.h>
- #endif
-
- #include "const.h"
- #include "gwerrors.h"
- #include "mytypes.h"
- #include "globals.h"
- #include "utils.h"
- #include "network.h"
- #include "pop.types.h"
- #include "pop.constants.h"
- #include "parser.h"
- #include "spoolsystem.h"
-
- #include "pop.protocol.h"
-
- OSErr POP_InitiateConnection(unsigned long popAddress,unsigned short popPort,char *user,char *password,unsigned long *connID)
- {
- OSErr err;
- Ptr response;
- unsigned long responseLength;
- char command[256];
- GetCRLFStates state;
-
- TCP_FlushBytes();
-
- err = TCP_CreateStream(connID);
- if (err!=noErr) {
- return err;
- }
-
- err = TCP_ActiveOpen(*connID,popAddress,popPort,kPOPTimeout);
- if (err!=noErr) {
- TCP_ReleaseStream(*connID);
- return kInvalidPopServer;
- }
-
- state = sCRLFNormal;
- POP_GetTextToCRLF(*connID,&response,&responseLength,&state);
- if (response)
- DisposPtrChk(response);
-
- strcpy(command,"USER ");
- strcat(command,user);
- err = POP_Command(*connID,command,&response,&responseLength);
- if (err!=noErr) {
- POP_CloseConnection(*connID);
- if (err==kPOPError)
- err = kInvalidUsername;
- return err;
- }
- DisposPtrChk(response);
-
- strcpy(command,"PASS ");
- strcat(command,password);
- err = POP_Command(*connID,command,&response,&responseLength);
- if (err!=noErr) {
- POP_CloseConnection(*connID);
- if (err==kPOPError)
- err = kInvalidPasssword;
- return err;
- }
- DisposPtrChk(response);
-
- return err;
- }
-
-
- OSErr POP_GetDropStats(unsigned long connID,short *numMessages,long *messageSize)
- {
- char command[256];
- char *word,*responsePtr;
- Ptr response;
- unsigned long responseLength;
- long number;
- OSErr err;
-
- strcpy(command,"STAT");
- err = POP_Command(connID,command,&response,&responseLength);
- if (err!=noErr) {
- return err;
- }
-
- /* get drop text */
-
- responsePtr = (char *)response;
- GetWord(&word,&responsePtr); // get rid of +OK / -ERR
- GetNumber(&number,&responsePtr); // get number of messages
- *numMessages = (short) number;
- GetNumber(&number,&responsePtr); // get size of mailbox in bytes
- *messageSize = number;
-
- DisposPtrChk(response);
- return err;
- }
-
-
- OSErr POP_GetMessageIDs(unsigned long connID,TMsgIDList *messageIDList,short *numMessageIDs)
- {
- char command[256];
- Ptr response;
- unsigned long responseLength;
- char *responsePtr;
- long number;
- short numMsgs,msgIndex;
- OSErr err;
- GetTermStates state;
-
- strcpy(command,"LIST");
- err = POP_Command(connID,command,&response,&responseLength);
- if (err!=noErr) {
- return err;
- }
- DisposPtrChk(response);
-
- state = sGotLF;
- err = POP_GetTextToTerminator(connID,&response,&responseLength,&state);
- if (err!=noErr) {
- return err;
- }
-
- if (responseLength==0) {
- *numMessageIDs = 0;
- return err;
- }
-
- responsePtr = (char *)response;
- numMsgs = *numMessageIDs = CountLines(responsePtr);
- if (numMsgs > 0) {
-
- *messageIDList = (TMsgIDList)NewPtrChk(sizeof(TMsgID)*numMsgs);
- if ((err=MemError())!=noErr) {
- DisposPtrChk(response);
- return err;
- }
-
- msgIndex = 0;
- while (*responsePtr) {
- GetNumber(&number,&responsePtr); // get message ID
- (*messageIDList)[msgIndex] = (TMsgID)number;
- GetNumber(&number,&responsePtr); // get message size & discard in this version
- msgIndex++;
- }
-
- }
- DisposPtrChk(response);
- return err;
- }
-
-
- OSErr POP_GetMessage(unsigned long connID,TMsgID messageID,Ptr *header,FSSpec *spoolSpec)
- {
- char command[256],messageIDStr[256];
- Ptr response,bodyResponse;
- unsigned long responseLength;
- OSErr err;
- GetCRLFCRLFStates crlfcrlfState;
- GetCRLFStates crlfState;
- Boolean first;
-
- strcpy(command,"RETR ");
- MessageIDToString(messageID,messageIDStr);
- strcat(command,messageIDStr);
- err = POP_Command(connID,command,&response,&responseLength);
- if (err!=noErr) {
- return err;
- }
- DisposPtrChk(response);
-
- // get message header (into a memory buffer)
-
- crlfcrlfState = sCRLFCRLFNormal;
- err = POP_GetTextToCRLFCRLF(connID,&response,&responseLength,&crlfcrlfState);
- if (err!=noErr) {
- return err;
- }
-
- if (responseLength==0)
- return kErrResponse;
- StripLF((char *)response,&responseLength);
- *header = response;
-
- // get message body (into a disk file)
-
- crlfState = sGotLF;
- first = true;
- do {
- err = POP_GetTextToTerminator(connID,&bodyResponse,&responseLength,&crlfState);
- if (err!=noErr)
- return err;
- StripLF((char *)bodyResponse,&responseLength);
- if (first) {
- SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,bodyResponse,responseLength);
- first = false;
- }
- else
- AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,bodyResponse,responseLength);
- DisposPtrChk(bodyResponse);
- } while (crlfState!=sFinished);
-
- return err;
- }
-
-
- OSErr POP_DeleteMessage(unsigned long connID,TMsgID messageID)
- {
- char command[256],messageIDStr[256];
- Ptr response;
- unsigned long responseLength;
- OSErr err;
-
- strcpy(command,"DELE ");
- MessageIDToString(messageID,messageIDStr);
- strcat(command,messageIDStr);
- err = POP_Command(connID,command,&response,&responseLength);
- if (err!=noErr) {
- return err;
- }
- DisposPtrChk(response);
- return err;
- }
-
-
- OSErr POP_CloseConnection(unsigned long connID)
- {
- char command[256];
- Ptr response;
- unsigned long responseLength;
- OSErr err;
-
- strcpy(command,"QUIT");
- err = POP_Command(connID,command,&response,&responseLength);
- if (err==noErr) {
- DisposPtrChk(response);
- }
-
- err = TCP_CloseConnection(connID,kPOPTimeout);
- err = TCP_ReleaseStream(connID);
-
- TCP_FlushBytes();
-
- return err;
- }
-
-
- OSErr POP_Command(unsigned long connID,char *command,Ptr *response,unsigned long *responseLength)
- {
- char sendCommand[256];
- unsigned short sendLength;
- OSErr err;
- GetCRLFStates state;
-
- strcpy(sendCommand,command);
- strcat(sendCommand,kCRLF);
- sendLength = strlen(sendCommand);
-
- err = TCP_Send(connID,sendCommand,sendLength,true,kPOPTimeout);
- if (err!=noErr)
- return err;
-
- state = sCRLFNormal;
- err = POP_GetTextToCRLF(connID,response,responseLength,&state);
- if (err!=noErr)
- return err;
-
- if (*responseLength>0 && (*response)[0]=='-') {
- DisposPtrChk(*response);
- return kPOPError;
- }
-
- return noErr;
- }
-
-
- OSErr POP_GetTextToTerminator(unsigned long connID,Ptr *response,unsigned long *responseLength,GetTermStates *savedState)
- {
- OSErr err;
- unsigned long receivedBytes;
- Handle dataHandle;
- Ptr dataPtr;
- unsigned long handleSize;
- unsigned char dataByte;
- GetTermStates stateMachine;
-
- stateMachine = *savedState; // NOTE: normally, we start at sGotLF
-
- receivedBytes = 0;
- handleSize = kTransactionBite;
- dataHandle = NewHandleChk(handleSize);
- if (MemError()!=noErr)
- return MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
-
- do {
- err = TCP_ReadByte(connID,&dataByte,kPOPTimeout);
- if (err==noErr) {
-
- /* store data */
-
- dataPtr[receivedBytes++] = dataByte;
-
- /* advance state machine */
-
- if (dataByte==CR) {
- if (stateMachine==sNormal || stateMachine==sGotTerminator)
- stateMachine++;
- else
- stateMachine==sNormal;
- }
- else if (dataByte==LF) {
- if (stateMachine==sGotCR || stateMachine==sGotPostTermCR)
- stateMachine++;
- else
- stateMachine==sNormal;
- }
- else if (dataByte==kMessageTerminator) {
- if (stateMachine==sGotLF)
- stateMachine++;
- else
- stateMachine==sNormal;
- }
- else
- stateMachine = sNormal;
-
- if (receivedBytes==handleSize) {
- handleSize += kTransactionBite;
- HUnlock(dataHandle);
- SetHandleSize(dataHandle,handleSize);
- err = MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
- }
- }
- } while (err==noErr && handleSize <= kMaxPOPTransactionSize && stateMachine!=sFinished);
-
- if (stateMachine==sFinished)
- receivedBytes -= 3;
-
- *responseLength = receivedBytes;
-
- if (receivedBytes!=0) {
- *response = NewPtrChk(receivedBytes+1);
- if (MemError()!=noErr)
- return MemError();
- BlockMove(dataPtr,*response,receivedBytes);
- (*response)[receivedBytes++] = '\0'; // null terminate response
- }
-
- DisposHandleChk(dataHandle);
- *savedState = stateMachine;
-
- return err;
- }
-
-
- OSErr POP_GetTextToCRLF(unsigned long connID,Ptr *response,unsigned long *responseLength,GetCRLFStates *savedState)
- {
- OSErr err;
- unsigned long receivedBytes;
- Handle dataHandle;
- Ptr dataPtr;
- unsigned long handleSize;
- unsigned char dataByte;
- GetCRLFStates stateMachine;
-
- stateMachine = *savedState;
-
- receivedBytes = 0;
- handleSize = kTransactionBite;
- dataHandle = NewHandleChk(handleSize);
- if (MemError()!=noErr)
- return MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
-
- do {
- err = TCP_ReadByte(connID,&dataByte,kPOPTimeout);
- if (err==noErr) {
-
- /* store data */
-
- dataPtr[receivedBytes++] = dataByte;
-
- /* advance state machine */
-
- if (dataByte==CR) {
- if (stateMachine==sCRLFNormal)
- stateMachine++;
- else
- stateMachine==sCRLFNormal;
- }
- else if (dataByte==LF) {
- if (stateMachine==sCRLFGotCR)
- stateMachine++;
- else
- stateMachine==sCRLFNormal;
- }
- else
- stateMachine = sCRLFNormal;
-
- if (receivedBytes==handleSize) {
- handleSize += kTransactionBite;
- HUnlock(dataHandle);
- SetHandleSize(dataHandle,handleSize);
- err = MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
- }
- }
- } while (err==noErr && handleSize <= kMaxPOPTransactionSize && stateMachine!=sCRLFFinished);
-
- if (stateMachine==sCRLFFinished)
- receivedBytes -= 2;
-
- *responseLength = receivedBytes;
-
- if (receivedBytes!=0) {
- *response = NewPtrChk(receivedBytes+1);
- if ((err = MemError())!=noErr) {
- DisposHandleChk(dataHandle);
- return err;
- }
- BlockMove(dataPtr,*response,receivedBytes);
- (*response)[receivedBytes++] = '\0'; // null terminate response
- DisposHandleChk(dataHandle);
- }
-
- *savedState = stateMachine;
- return err;
- }
-
-
- OSErr POP_GetTextToCRLFCRLF(unsigned long connID,Ptr *response,unsigned long *responseLength,GetCRLFCRLFStates *savedState)
- {
- OSErr err;
- unsigned long receivedBytes;
- Handle dataHandle;
- Ptr dataPtr;
- unsigned long handleSize;
- unsigned char dataByte;
- GetCRLFCRLFStates stateMachine;
-
- stateMachine = *savedState;
-
- receivedBytes = 0;
- handleSize = kTransactionBite;
- dataHandle = NewHandleChk(handleSize);
- if (MemError()!=noErr)
- return MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
-
- do {
- err = TCP_ReadByte(connID,&dataByte,kPOPTimeout);
- if (err==noErr) {
-
- /* store data */
-
- dataPtr[receivedBytes++] = dataByte;
-
- /* advance state machine */
-
- if (dataByte==CR) {
- if ((stateMachine==sCRLFCRLFNormal) || (stateMachine==sCRLFCRLFGotLF))
- stateMachine++;
- else
- stateMachine==sCRLFCRLFNormal;
- }
- else if (dataByte==LF) {
- if ((stateMachine==sCRLFCRLFGotCR) || (stateMachine==sCRLFCRLFGetPostCR))
- stateMachine++;
- else
- stateMachine==sCRLFCRLFNormal;
- }
- else
- stateMachine = sCRLFCRLFNormal;
-
- if (receivedBytes==handleSize) {
- handleSize += kTransactionBite;
- HUnlock(dataHandle);
- SetHandleSize(dataHandle,handleSize);
- err = MemError();
- MoveHHi(dataHandle);
- HLock(dataHandle);
- dataPtr = *dataHandle;
- }
- }
- } while (err==noErr && handleSize <= kMaxPOPTransactionSize && stateMachine!=sCRLFCRLFFinished);
-
- if (stateMachine==sCRLFCRLFFinished)
- receivedBytes -= 4;
-
- *responseLength = receivedBytes;
-
- if (receivedBytes!=0) {
- *response = NewPtrChk(receivedBytes+1);
- if ((err = MemError())!=noErr) {
- DisposHandleChk(dataHandle);
- return err;
- }
- BlockMove(dataPtr,*response,receivedBytes);
- (*response)[receivedBytes++] = '\0'; // null terminate response
- DisposHandleChk(dataHandle);
- }
-
- *savedState = stateMachine;
- return err;
- }
-
-
- void MessageIDToString(TMsgID messageID,char *messageIDStr)
- {
- long msgIDLong;
-
- msgIDLong = (long) messageID;
- NumToString(msgIDLong,(StringPtr)messageIDStr);
- p2cstr((StringPtr)messageIDStr);
- }
-